package com.honeywen.mymvc.test;

import com.alibaba.fastjson.JSONObject;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author wangwei
 * @date 2019/5/6
 */
public class HashSign {
    private static final List<String> notSign = new ArrayList<String>();

    static {
        notSign.add("hash");
    }

    public static String encrypt_sha256(String secret, String message) {
        String hash = "";
        try {

            if (secret == null || secret.equals("")) {
                return null;
            }
            if (message == null) {
                return null;
            }

            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);

            hash = byte2hex(sha256_HMAC.doFinal(message.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return hash;
    }

    private static String byte2hex(final byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            // 以十六进制（基数 16）无符号整数形式返回一个整数参数的字符串表示形式。
            stmp = (Integer.toHexString(b[n] & 0xFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs;
    }

    /**
     * sha-256加签名
     *
     * @param reqObj
     * @param secret
     * @return
     * @author yuan
     */
    public static String addSignSHA256(JSONObject reqObj, String secret) {
        // 生成待签名串
        String sign_src = genSignData(reqObj);
        try {
            return encrypt_sha256(secret, sign_src);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 生成待签名串
     *
     * @param jsonObject
     * @return
     * @author yuan
     */
    public static String genSignData(JSONObject jsonObject) {
        StringBuffer content = new StringBuffer();

        // 按照key做首字母升序排列
        List<String> keys = new ArrayList<String>(jsonObject.keySet());
        Collections.sort(keys, String.CASE_INSENSITIVE_ORDER);
        for (int i = 0; i < keys.size(); i++) {
            String key = (String) keys.get(i);
            if ("sign".equals(key) || notSign.contains(key)) {
                continue;
            }
            String value = jsonObject.getString(key);
            // 空串不参与签名
            if (isnull(value)) {
                continue;
            }
            content.append((i == 0 ? "" : "&") + key + "=" + value);

        }
        String signSrc = content.toString();
        if (signSrc.startsWith("&")) {
            signSrc = signSrc.replaceFirst("&", "");
        }
        return signSrc;
    }

    /**
     * str空判断
     *
     * @param str
     * @return
     */
    public static boolean isnull(String str) {
        if (null == str || str.equalsIgnoreCase("null") || str.equals("")) {
            return true;
        } else
            return false;
    }

    public static JSONObject addSign(JSONObject jsonObject, String secret) {

        String hashId = HashSign.addSignSHA256(jsonObject, secret);
        jsonObject.put("hash", hashId);
        return jsonObject;

    }


    /**
     * 签名验证
     *
     * @param reqObj
     * @return boolean
     */
    public static boolean checkSign(JSONObject reqObj, String secret) {

        if (reqObj == null) {
            return false;
        }
        String sign = reqObj.getString("sign");
//         生成待签名串
        String sign_src = genSignData(reqObj);
        System.out.println("他们的: " + sign);

        try {
            String target_sign = HashSign.addSignSHA256(reqObj, secret);
            System.out.println("我们的: " + target_sign);
            if (sign.equals(target_sign)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    public static void main(String[] args) {


        JSONObject jsonObject = new JSONObject();
        jsonObject.put("applyDt", "20180720160000");
        jsonObject.put("applyNo", "1912");
        jsonObject.put("mobileNo", "2349072978725");
        jsonObject.put("reason", "rule_7");
        jsonObject.put("score", "0");
        jsonObject.put("userId", "331823827904364544");


        JSONObject signedObj = HashSign.addSign(jsonObject, "opay-service");
        System.out.println(signedObj.toJSONString());
        System.out.println(HashSign.checkSign(signedObj, "opay-service"));



    }
}
